#ifndef WIIMOTE_H_
#define WIIMOTE_H_

#endif /*WIIMOTE_H_*/

#include "wiiuse.h"

/**************************************************************************
 *    I love wiiuse!                                                      *
 *     Madd Dope-Ass-Gangster Props to Michael Laforest.                  *
 *       -Tag                                                             *
 **************************************************************************/


/**************************************************************************
 *   Wiimote.cpp                                                          *
 *                                                                        *
 *   Copyright (C) 2008 Paul Tagliamonte ( paultag@ubuntu.com )           *
 *   This program is free software; you can redistribute it and/or modify *
 *   it under the terms of the GNU General Public License as published by *
 *   the Free Software Foundation; either version 1, or (at your option)  *
 *   any later version.                                                   *
 *                                                                        *
 *   This program is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of       *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *   GNU General Public License for more details.                         *
 *                                                                        *
 *   You should have received a copy of the GNU General Public License    *
 *   along with this program; if not, write to the Free Software          *
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
 *                                                                        *
 **************************************************************************/

/* User Serviceable Parts */
#define __DEFAULT_MAX       4
#define __DEFAULT_TIMEOUT   5

/*
 *
 * Please do not fiddle below this point, unless you know  how to play with Classes.
 * also, Please be so kind as to not change any copyright info ( or file info ) :)
 *
 */

/* File Info */
#define __FILE_NAME     "Wiimote.h"
#define __APP_NAME      "Wiimote"
#define __VERSION       "0.8"

/* Copyright Info */
#define __AUTHOR        "Paul Tagliamonte"
#define __AUTHOR_EMAIL  "paultag [at ] ubuntu [dot ] com"
#define __LICENSE       "GNU GPLv3"

/* I do believe we are Ballin'. */
#define __BALLING       true

class Wiimote {

    wiimote**  _wiimotes     ;  // this is full of struct wiimote_t* wm
          int  _found        ;
          int  _connected    ;
          int  _max_wiimotes ;
          int  _timeout      ;

    public:

        /*
         * Constructor. Lets set defaults.
         * The defaults are in the header define.
         * Whoot.
         */
        Wiimote() {
            _max_wiimotes = __DEFAULT_MAX;
                 _timeout = __DEFAULT_TIMEOUT;
                _wiimotes =  wiiuse_init(_max_wiimotes );
        }
        Wiimote(
                const int max_wiimotes
        ) {
            _max_wiimotes = max_wiimotes;
                 _timeout = __DEFAULT_TIMEOUT;
                _wiimotes =  wiiuse_init(_max_wiimotes );
        }
        Wiimote(
                const int max_wiimotes,
                const int timeout
        ) {
            _max_wiimotes = max_wiimotes;
                 _timeout = timeout;
                _wiimotes =  wiiuse_init(_max_wiimotes );
        }

       /*
        *
        * Vanity Here. Please Do not edit unless you change this file in a significant way.
        * Note, correcting my bad grammar and / or spelling does not constitute a major edit :P
        * Love,
        * Tag
        *
        */
        void copyright() {
            printf(
                "  -------------------------------------------\n"
                "  Wiimote, C++ Class to iterface to libwiiuse\n"
                "  Version " __VERSION " Copyright (c) " __LICENSE "\n"
                "  " __AUTHOR " (" __AUTHOR_EMAIL ")\n"
            );
	}

        /*
         * Check to see that the status is not 2048
         * I have checked the status of a disconnected wiimote, not an unknown node.
         */
        bool is_connected( const int wiimote ) {
            return ( _wiimotes[wiimote]->state != 2048 );
        }

        /*
         * Check to see if all are disconnected
         * 
         */

        bool active() {
            bool ret = false;
            
            for ( int i = 0; i < this->get_connected(); ++i ) {
                if ( this->is_connected( i ) ) {
                    ret = true;
                }
            }
            return ret;
        }

        /*
         * Return the current Wiimote Status.
         * Fun, Fun, Fun
         */
        int state( const int wiimote ) {
            return _wiimotes[wiimote]->state;
        }

        /*
         * Public Interface to the _timeout int value.
         * This is to let the end user set the timeout w/o changing src.
         */
        void set_timeout( const int timeout ) {
            _timeout = timeout;
        }

        /*
         * Public Interface to the _timeout int value
         * This returns the current _timeout value.
         */
        int get_timeout() {
            return _timeout;
        }

        /*
         * Public Interface to the _connected int value
         * This returns the current _connected value.
         */
        int get_connected() {
            return _connected;
        }

        /*
         * Public Interface to the _found int value
         * This returns the current _found value.
         */
        int get_found() {
            return _found;
        }

        /*
         * Public Interface to the _max_wiimotes int value
         * this returns the current wiimote max.
         */
        int get_max_wiimotes() {
            return _max_wiimotes;
        }

        /*
         * find();
         *
         * This starts the hunt for local wiimotes. It pulls from this->_max_wiimotes
         * and this->_timeout. ( also our **wiimote _wiimotes wiimote array)
         * returns number of wiimotes in the area
         *
         */
        int find() {
            _found = wiiuse_find( _wiimotes, _max_wiimotes, _timeout );
            return _found;
        }

        /*
         * connect();
         *
         * This starts the hunt for local wiimotes. It pulls from this->_max_wiimotes
         * and this->_timeout. ( also our **wiimote _wiimotes wiimote array)
         * returns number of connected wiimotes
         *
         */
        int connect() {
            find();
            _connected = wiiuse_connect( _wiimotes, _max_wiimotes );
            return _connected;
        }

       /*
        * pending();
        *
        * Pending checks to see if any of our wiimotes has an event.
        *
        * TODO: Return the wiimote number.
        *
        */
        bool pending() {
            if ( wiiuse_poll( _wiimotes, _max_wiimotes ) ) {
                return 1;
            } else {
                return 0;
            }
        }
        
       /*
        * get_event( int );
        * This returns the Wiimote's event value.
        */
        WIIUSE_EVENT_TYPE get_event( const int wiimote ) {
                return _wiimotes[wiimote]->event;
        }

       /*
        * enable_motion( int );
        * This enables the wiimote motion sensing
        */
        void enable_acc( const int wiimote ) {
            wiiuse_motion_sensing( _wiimotes[wiimote], 1);
        }

       /*
        * disable_motion( int );
        * This enables the wiimote motion sensing
        */
        void disable_acc( const int wiimote ) {
            wiiuse_motion_sensing( _wiimotes[wiimote], 0);
        }
       /*
        * using_acc( int );
        * Checks to see if the Accelerometer is enabled.
        */
        bool using_acc( const int wiimote ) {
            if (WIIUSE_USING_ACC( _wiimotes[wiimote] )) { return 1; } else { return 0; }
        }

       /*
        * using_ir( int );
        * Checks to see if IR is enabled.
        */
        bool using_ir( const int wiimote ) {
            if (WIIUSE_USING_IR( _wiimotes[wiimote] )) { return 1; } else { return 0; }
        }

       /*
        * toggle_rumble( int );
        * This toggles the wiimote rumble
        */
        void toggle_rumble( const int wiimote ) {
            wiiuse_toggle_rumble( _wiimotes[wiimote] );
        }

       /*
        * set_rumble( int );
        * This enables the wiimote rumble
        */
        void enable_rumble( const int wiimote ) {
            wiiuse_rumble( _wiimotes[wiimote], 1 );
        }

       /*
        * disable_rumble( int );
        * This disables the wiimote rumble
        */
        void disable_rumble( const int wiimote ) {
            wiiuse_rumble( _wiimotes[wiimote], 0 );
        }

       /*
        * varable_rumble( int, int );
        * This disables the wiimote rumble
        */
        void varable_rumble( const int wiimote, const int cycles, const int pulse ) {
            for ( int i = 0; i < cycles; i++ ) {
                wiiuse_toggle_rumble( _wiimotes[wiimote] );
                usleep( pulse );
            }
            disable_rumble( wiimote );
        }

       /*
        * set_led_bitmask( int, int );
        * This sets the LED Bitmask
        */
        void set_led_bitmask( const int wiimote, const int bitmask ) {
            wiiuse_set_leds( _wiimotes[wiimote], bitmask );
        }

       /*
        * enable_ir( int );
        * This sets the IR Sensor to Enabled
        */
        void enable_ir( const int wiimote ) {
            wiiuse_set_ir( _wiimotes[wiimote], 1);
        }

       /*
        * disable_ir( int );
        * This sets the IR Sensor to Disabled
        */
        void disable_ir( const int wiimote ) {
            wiiuse_set_ir( _wiimotes[wiimote], 0);
        }

       /*
        * roll( int );
        * This gets the current roll if the acc is enabled.
        */
        double roll( const int wiimote ) {
            if (WIIUSE_USING_ACC( _wiimotes[wiimote] )) {
                return _wiimotes[wiimote]->orient.a_roll;
            } else {
                return 0;
            }
        }

        // [i love lamp]

       /*
        * pitch( int );
        * This gets the current roll if the acc is enabled.
        */
        double pitch( const int wiimote ) {
            if (WIIUSE_USING_ACC( _wiimotes[wiimote] )) {
                return _wiimotes[wiimote]->orient.a_pitch;
            } else {
                return 0;
            }
        }

       /*
        * yaw( int );
        * This gets the current roll if the acc is enabled.
        */
        double yaw( const int wiimote ) {
            if (WIIUSE_USING_ACC( _wiimotes[wiimote] )) {
                return _wiimotes[wiimote]->orient.yaw;
            } else {
                return 0;
            }
        }

       /*
        * ir_x( int );
        * This gets the current IR X Position, if there is an IR signal.
        * and IR is enabled
        */
        double ir_x( const int wiimote ) {
               if (WIIUSE_USING_IR(_wiimotes[wiimote])) {
                   for ( int i = 0; i < this->get_connected(); ++i ) {
                        if (_wiimotes[wiimote]->ir.dot[i].visible) {
                             return _wiimotes[wiimote]->ir.dot[i].x ;
                        }
                   }
               }
               return 0;
        }

       /*
        * ir_y( int );
        * This gets the current IR Y Position, if there is an IR signal.
        * and IR is enabled
        */
        double ir_y( const int wiimote ) {
            if (WIIUSE_USING_IR(_wiimotes[wiimote])) {
                for ( int i = 0; i < this->get_connected(); ++i ) {
                    if (_wiimotes[wiimote]->ir.dot[i].visible) {
                        return _wiimotes[wiimote]->ir.dot[i].y ;
                    }
                }
            }
            return 0;
        }

       /*
        * using_speaker( int );
        * This gets the speaker usage, returns as bool
        */
        bool using_speaker( const int wiimote ) {
            if (WIIUSE_USING_SPEAKER(_wiimotes[wiimote])) {
               return 1;
            }
            return 0;
        }

       /*
        * battery_level( int );
        * This gets the battery level
        */
        float battery_level( const int wiimote ) {
               return _wiimotes[wiimote]->battery_level;
        }

       /*
        * led_bitmask( int );
        * returns the LED Bitmask.
        */
        int led_bitmask( int wiimote ) {
               bool _one = WIIUSE_IS_LED_SET( _wiimotes[wiimote], 1);
               bool _two = WIIUSE_IS_LED_SET( _wiimotes[wiimote], 2);
             bool _three = WIIUSE_IS_LED_SET( _wiimotes[wiimote], 3);
              bool _four = WIIUSE_IS_LED_SET( _wiimotes[wiimote], 4);
            int _bitmask = 0;
              if ( _one ) { _bitmask = _bitmask + 1; }
              if ( _two ) { _bitmask = _bitmask + 2; }
            if ( _three ) { _bitmask = _bitmask + 4; }
             if ( _four ) { _bitmask = _bitmask + 8; }

            return _bitmask;
        }

        int exp_type( int wiimote ) {
            return _wiimotes[wiimote]->exp.type;
        }
        /*
         *
         * OK From here on out, we are checking buttons, etc.
         *
         */

        /*
         * Up on the D-Pad, takes the wiimote number in the array.
         */
        bool up_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_UP)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * Down on the D-Pad, takes the wiimote number in the array.
         */
        bool down_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_DOWN)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * Right on the D-Pad, takes the wiimote number in the array.
         */
        bool right_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_RIGHT)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * Left on the D-Pad, takes the wiimote number in the array.
         */
        bool left_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_LEFT)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * A, takes the wiimote number in the array.
         */
        bool a_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_A)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * B, takes the wiimote number in the array.
         */
        bool b_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_B)) {
                return 1;
            } else {
                return 0;
            }
        }

        // NEIL, PLAY THE DRUM SOLO OF LIFE!

        /*
         * 1, takes the wiimote number in the array.
         */
        bool one_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_ONE)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * 2, takes the wiimote number in the array.
         */
        bool two_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_TWO)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * Plus, takes the wiimote number in the array.
         */
        bool plus_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_PLUS)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * Minus, takes the wiimote number in the array.
         */
        bool minus_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_MINUS)) {
                return 1;
            } else {
                return 0;
            }
        }

        /*
         * Home, takes the wiimote number in the array.
         */
        bool home_is_pressed( const int wiimote ) {
            if (IS_PRESSED(_wiimotes[wiimote], WIIMOTE_BUTTON_HOME)) {
                return 1;
            } else {
                return 0;
            }
        }
    // End public shenanigans

};
